/*******************************************************************************
 * File name: 		gpio.c
 * Description: 
 * Project: 		_lpc1788
 * Target: 			LPC1788
 * Compiler: 		arm-none-eabi-gcc
 * Date: 			05-07-2012
 * Author: 			Kuba
 * Based on: 		---
 ******************************************************************************/

/*==============================================================================
 Includes
==============================================================================*/
# include <stdlib.h>
# include "LPC177x_8x.h"
# include "core_cm3.h"
# include "macros.h"
# include "gpio.h"

/*==============================================================================
 Defines
==============================================================================*/
# define IRQ_PORT			2
# define PORT_PIN			32

/*==============================================================================
 Types
==============================================================================*/

/*==============================================================================
 Globals
==============================================================================*/
static void (*gpioService[IRQ_PORT][PORT_PIN]) (void);	/* array of pointers to user services */

/*==============================================================================
 Static ISR prototypes
==============================================================================*/

/*==============================================================================
 Static function prototypes
==============================================================================*/
static void dummyService (void);
/*==============================================================================
 Global function definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name:		gpio32SetDir
 description:		set direction for 32 bit GPIO
 parameters:		port number, value, direction (output/input)
 returned value:	true or false
------------------------------------------------------------------------------*/
bool gpio32SetDir 	(const enum gpioPort port, const uint32 value, const enum gpioDirection dir)
{
	LPC_GPIO_TypeDef *ptr = NULL;

	switch (port)
	{
	case gpioPORT0:
		ptr = LPC_GPIO0;
		break;

	case gpioPORT1:
		ptr = LPC_GPIO1;
		break;

	case gpioPORT2:
		ptr = LPC_GPIO2;
		break;

	case gpioPORT3:
		ptr = LPC_GPIO3;
		break;

	case gpioPORT4:
		ptr = LPC_GPIO4;
		break;

	case gpioPORT5:
		ptr = LPC_GPIO5;
		break;

	default:
		return FALSE;
	}

	switch (dir)
	{
	case gpioOUTPUT:
		ptr->DIR |= value;
		break;

	case gpioINPUT:
		ptr->DIR &= ~value;
		break;

	default:
		return FALSE;
	}

	return TRUE;
}

/*------------------------------------------------------------------------------
 function name:		gpio32SetValue
 description:		set value for 32 bit GPIO port
 parameters:		port number, bit value
 returned value:	true or false
------------------------------------------------------------------------------*/
bool gpio32SetValue	(const enum gpioPort port, const uint32 value)
{
	switch (port)
	{
	case gpioPORT0:
		LPC_GPIO0->SET |= value;
		break;

	case gpioPORT1:
		LPC_GPIO1->SET |= value;
		break;

	case gpioPORT2:
		LPC_GPIO2->SET |= value;
		break;

	case gpioPORT3:
		LPC_GPIO3->SET |= value;
		break;

	case gpioPORT4:
		LPC_GPIO4->SET |= value;
		break;

	case gpioPORT5:
		LPC_GPIO5->SET |= value;
		break;

	default:
		return FALSE;
	}

	return TRUE;
}

/*------------------------------------------------------------------------------
 function name:		gpio32ClearValue
 description:		clear value for 32 bit GPIO port
 parameters:		port number, bit value
 returned value:	true or false
------------------------------------------------------------------------------*/
bool gpio32ClearValue (const enum gpioPort port, const uint32 value)
{
	switch (port)
	{
	case gpioPORT0:
		LPC_GPIO0->CLR |= value;
		break;

	case gpioPORT1:
		LPC_GPIO1->CLR |= value;
		break;

	case gpioPORT2:
		LPC_GPIO2->CLR |= value;
		break;

	case gpioPORT3:
		LPC_GPIO3->CLR |= value;
		break;

	case gpioPORT4:
		LPC_GPIO4->CLR |= value;
		break;

	case gpioPORT5:
		LPC_GPIO5->CLR |= value;
		break;

	default:
		return FALSE;
	}

	return TRUE;
}

/*------------------------------------------------------------------------------
 function name:		gpio32ToggleValue
 description:		toggle value for 32 bit GPIO port
 parameters:		port number, bit value
 returned value:	true or false
------------------------------------------------------------------------------*/
bool gpio32ToggleValue (const enum gpioPort port, const uint32 value)
{
	switch (port)
	{
	case gpioPORT0:
		LPC_GPIO0->PIN ^= value;
		break;

	case gpioPORT1:
		LPC_GPIO1->PIN ^= value;
		break;

	case gpioPORT2:
		LPC_GPIO2->PIN ^= value;
		break;

	case gpioPORT3:
		LPC_GPIO3->PIN ^= value;
		break;

	case gpioPORT4:
		LPC_GPIO4->PIN ^= value;
		break;

	case gpioPORT5:
		LPC_GPIO5->PIN ^= value;
		break;

	default:
		return FALSE;
	}

	return TRUE;
}

/*------------------------------------------------------------------------------
 function name:		gpio32ReadValue
 description:		read value from 32 bit GPIO port
 parameters:		port number
 returned value:	current value of port
------------------------------------------------------------------------------*/
uint32 gpio32ReadValue (const enum gpioPort port)
{
	switch (port)
	{
	case gpioPORT0:
		return LPC_GPIO0->PIN;
		break;

	case gpioPORT1:
		return LPC_GPIO1->PIN;
		break;

	case gpioPORT2:
		return LPC_GPIO2->PIN;
		break;

	case gpioPORT3:
		return LPC_GPIO3->PIN;
		break;

	case gpioPORT4:
		return LPC_GPIO4->PIN;
		break;

	case gpioPORT5:
		return LPC_GPIO5->PIN;
		break;

	default:
		return 0xFFFFFFFF;
	}
}

/*------------------------------------------------------------------------------
 function name:		gpio32InitIrq
 description:		init GPIO port to generate interrupt. NOTE: only PORT0 and
 	 	 	 	 	 PORT2 can generate interrupt.
 parameters:		port number, pin, IRQ configuration, const pointer to user service
 returned value:	true or false
------------------------------------------------------------------------------*/
bool gpio32InitIrq	(const enum gpioPort port,
					const uint32 pin,
					const enum gpioIrqConf irqConf,
					const enum irqPriority priority,
					void (*const service)(void))
{
	uint32 i;

	/* check if service is not zero */
	if (service == 0)
	{
		gpioService[i][pin] = dummyService;	/* pinNumber is converted from bin to dec */
	}
	else
	{
		gpioService[i][pin] = service;
	}

	switch (port)
	{
	case gpioPORT0:
		i = 0;

		switch (irqConf)
		{
		case gpioRISING_EDGE:
			LPC_GPIOINT->IO0IntEnR |= (1 << pin);
			break;

		case gpioFALLING_EDGE:
			LPC_GPIOINT->IO0IntEnF |= (1 << pin);
			break;

		default:
			return FALSE;
		}
		break;

	case gpioPORT2:
		i = 1;

		switch (irqConf)
		{
		case gpioRISING_EDGE:
			LPC_GPIOINT->IO2IntEnR |= (1 << pin);
			break;

		case gpioFALLING_EDGE:
			LPC_GPIOINT->IO2IntEnF |= (1 << pin);
			break;

		default:
			return FALSE;
		}
		break;

	default:
		return FALSE;
	}

	NVIC_SetPriority(GPIO_IRQn, priority);
	NVIC_EnableIRQ(GPIO_IRQn);

	return TRUE;
}

/*==============================================================================
 Static function definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name:		dummyService
 description:		only returns- to init function pointers
 parameters:		none
 returned value:	none
------------------------------------------------------------------------------*/
static void dummyService (void)
{
	return ;
}

/*==============================================================================
 ISR definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name:		GPIO_IRQHandler
 description:		GPIO ISR
 parameters:		none
 returned value:	none
------------------------------------------------------------------------------*/
void GPIO_IRQHandler (void)
{
	uint32 p0f;		/* port 0 falling egde interrupt status */
	uint32 p0r;		/* port 0 rising egde interrupt status */
	uint32 p2f;		/* port 2 falling egde interrupt status */
	uint32 p2r;		/* port 2 rising egde interrupt status */

	p0f = LPC_GPIOINT->IO0IntStatF;
	p0r = LPC_GPIOINT->IO0IntStatR;
	p2f = LPC_GPIOINT->IO2IntStatF;
	p2r = LPC_GPIOINT->IO2IntStatR;

	/* check port 0 */
	if(CHECK_BIT(p0f, 0) || CHECK_BIT(p0r, 0))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(0);		/* clear interrupt */
		(*gpioService[0][0])();						/* call user service */
	}
	else if(CHECK_BIT(p0f, 1) || CHECK_BIT(p0r, 1))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(1);
		(*gpioService[0][1])();
	}
	else if(CHECK_BIT(p0f, 2) || CHECK_BIT(p0r, 2))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(2);
		(*gpioService[0][2])();
	}
	else if(CHECK_BIT(p0f, 3) || CHECK_BIT(p0r, 3))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(3);
		(*gpioService[0][3])();

	}
	else if(CHECK_BIT(p0f, 4) || CHECK_BIT(p0r, 4))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(4);
		(*gpioService[0][4])();
	}
	else if(CHECK_BIT(p0f, 5) || CHECK_BIT(p0r, 5))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(5);
		(*gpioService[0][5])();
	}
	else if(CHECK_BIT(p0f, 6) || CHECK_BIT(p0r, 6))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(6);
		(*gpioService[0][6])();
	}
	else if(CHECK_BIT(p0f, 7) || CHECK_BIT(p0r, 7))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(7);
		(*gpioService[0][7])();
	}
	else if(CHECK_BIT(p0f, 8) || CHECK_BIT(p0r, 8))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(8);
		(*gpioService[0][8])();
	}
	else if(CHECK_BIT(p0f, 9) || CHECK_BIT(p0r, 9))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(9);
		(*gpioService[0][9])();
	}
	else if(CHECK_BIT(p0f, 10) || CHECK_BIT(p0r, 10))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(10);
		(*gpioService[0][10])();
	}
	else if(CHECK_BIT(p0f, 11) || CHECK_BIT(p0r, 11))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(11);
		(*gpioService[0][11])();
	}
	else if(CHECK_BIT(p0f, 12) || CHECK_BIT(p0r, 12))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(12);
		(*gpioService[0][12])();
	}
	else if(CHECK_BIT(p0f, 13) || CHECK_BIT(p0r, 13))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(13);
		(*gpioService[0][13])();
	}
	else if(CHECK_BIT(p0f, 14) || CHECK_BIT(p0r, 14))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(14);
		(*gpioService[0][14])();
	}
	else if(CHECK_BIT(p0f, 15) || CHECK_BIT(p0r, 15))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(15);
		(*gpioService[0][15])();
	}
	else if(CHECK_BIT(p0f, 16) || CHECK_BIT(p0r, 16))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(16);
		(*gpioService[0][16])();
	}
	else if(CHECK_BIT(p0f, 17) || CHECK_BIT(p0r, 17))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(17);
		(*gpioService[0][17])();
	}
	else if(CHECK_BIT(p0f, 18) || CHECK_BIT(p0r, 18))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(18);
		(*gpioService[0][18])();
	}
	else if(CHECK_BIT(p0f, 19) || CHECK_BIT(p0r, 19))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(19);
		(*gpioService[0][19])();
	}
	else if(CHECK_BIT(p0f, 20) || CHECK_BIT(p0r, 20))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(20);
		(*gpioService[0][20])();
	}
	else if(CHECK_BIT(p0f, 21) || CHECK_BIT(p0r, 21))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(21);
		(*gpioService[0][21])();
	}
	else if(CHECK_BIT(p0f, 22) || CHECK_BIT(p0r, 22))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(22);
		(*gpioService[0][22])();
	}
	else if(CHECK_BIT(p0f, 23) || CHECK_BIT(p0r, 23))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(23);
		(*gpioService[0][23])();
	}
	else if(CHECK_BIT(p0f, 24) || CHECK_BIT(p0r, 24))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(24);
		(*gpioService[0][24])();
	}
	else if(CHECK_BIT(p0f, 25) || CHECK_BIT(p0r, 25))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(25);
		(*gpioService[0][25])();
	}
	else if(CHECK_BIT(p0f, 26) || CHECK_BIT(p0r, 26))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(26);
		(*gpioService[0][26])();
	}
	else if(CHECK_BIT(p0f, 27) || CHECK_BIT(p0r, 27))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(27);
		(*gpioService[0][27])();
	}
	else if(CHECK_BIT(p0f, 28) || CHECK_BIT(p0r, 28))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(28);
		(*gpioService[0][28])();
	}
	else if(CHECK_BIT(p0f, 29) || CHECK_BIT(p0r, 29))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(29);
		(*gpioService[0][29])();
	}
	else if(CHECK_BIT(p0f, 30) || CHECK_BIT(p0r, 30))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(30);
		(*gpioService[0][30])();
	}
	else if(CHECK_BIT(p0f, 31) || CHECK_BIT(p0r, 31))
	{
		LPC_GPIOINT->IO0IntClr |= SET_BIT(31);
		(*gpioService[0][31])();
	}
	/* check port 2 */
	if(CHECK_BIT(p2f, 0) || CHECK_BIT(p2r, 0))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(0);
		(*gpioService[1][0])();
	}
	else if(CHECK_BIT(p2f, 1) || CHECK_BIT(p2r, 1))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(1);
		(*gpioService[1][1])();
	}
	else if(CHECK_BIT(p2f, 2) || CHECK_BIT(p2r, 2))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(2);
		(*gpioService[1][2])();
	}
	else if(CHECK_BIT(p2f, 3) || CHECK_BIT(p2r, 3))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(3);
		(*gpioService[1][3])();
	}
	else if(CHECK_BIT(p2f, 4) || CHECK_BIT(p2r, 4))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(4);
		(*gpioService[1][4])();
	}
	else if(CHECK_BIT(p2f, 5) || CHECK_BIT(p2r, 5))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(5);
		(*gpioService[1][5])();
	}
	else if(CHECK_BIT(p2f, 6) || CHECK_BIT(p2r, 6))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(6);
		(*gpioService[1][6])();
	}
	else if(CHECK_BIT(p2f, 7) || CHECK_BIT(p2r, 7))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(7);
		(*gpioService[1][7])();
	}
	else if(CHECK_BIT(p2f, 8) || CHECK_BIT(p2r, 8))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(8);
		(*gpioService[1][8])();
	}
	else if(CHECK_BIT(p2f, 9) || CHECK_BIT(p2r, 9))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(9);
		(*gpioService[1][9])();
	}
	else if(CHECK_BIT(p2f, 10) || CHECK_BIT(p2r, 10))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(10);
		(*gpioService[1][10])();
	}
	else if(CHECK_BIT(p2f, 11) || CHECK_BIT(p2r, 11))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(11);
		(*gpioService[1][11])();
	}
	else if(CHECK_BIT(p2f, 12) || CHECK_BIT(p2r, 12))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(12);
		(*gpioService[1][12])();
	}
	else if(CHECK_BIT(p2f, 13) || CHECK_BIT(p2r, 13))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(13);
		(*gpioService[1][13])();
	}
	else if(CHECK_BIT(p2f, 14) || CHECK_BIT(p2r, 14))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(14);
		(*gpioService[1][14])();
	}
	else if(CHECK_BIT(p2f, 15) || CHECK_BIT(p2r, 15))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(15);
		(*gpioService[1][15])();
	}
	else if(CHECK_BIT(p2f, 16) || CHECK_BIT(p2r, 16))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(16);
		(*gpioService[1][16])();
	}
	else if(CHECK_BIT(p2f, 17) || CHECK_BIT(p2r, 17))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(17);
		(*gpioService[1][17])();
	}
	else if(CHECK_BIT(p2f, 18) || CHECK_BIT(p2r, 18))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(18);
		(*gpioService[1][18])();
	}
	else if(CHECK_BIT(p2f, 19) || CHECK_BIT(p2r, 19))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(19);
		(*gpioService[1][19])();
	}
	else if(CHECK_BIT(p2f, 20) || CHECK_BIT(p2r, 20))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(20);
		(*gpioService[1][20])();
	}
	else if(CHECK_BIT(p2f, 21) || CHECK_BIT(p2r, 21))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(21);
		(*gpioService[1][21])();
	}
	else if(CHECK_BIT(p2f, 22) || CHECK_BIT(p2r, 22))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(22);
		(*gpioService[1][22])();
	}
	else if(CHECK_BIT(p2f, 23) || CHECK_BIT(p2r, 23))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(23);
		(*gpioService[1][23])();
	}
	else if(CHECK_BIT(p2f, 24) || CHECK_BIT(p2r, 24))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(24);
		(*gpioService[1][24])();
	}
	else if(CHECK_BIT(p2f, 25) || CHECK_BIT(p2r, 25))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(25);
		(*gpioService[1][25])();
	}
	else if(CHECK_BIT(p2f, 26) || CHECK_BIT(p2r, 26))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(26);
		(*gpioService[1][26])();
	}
	else if(CHECK_BIT(p2f, 27) || CHECK_BIT(p2r, 27))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(27);
		(*gpioService[1][27])();
	}
	else if(CHECK_BIT(p2f, 28) || CHECK_BIT(p2r, 28))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(28);
		(*gpioService[1][28])();
	}
	else if(CHECK_BIT(p2f, 29) || CHECK_BIT(p2r, 29))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(29);
		(*gpioService[1][29])();
	}
	else if(CHECK_BIT(p2f, 30) || CHECK_BIT(p2r, 30))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(30);
		(*gpioService[1][30])();
	}
	else if(CHECK_BIT(p2f, 31) || CHECK_BIT(p2r, 31))
	{
		LPC_GPIOINT->IO2IntClr |= SET_BIT(31);
		(*gpioService[1][31])();
	}
}

/******************************************************************************
* END OF FILE
******************************************************************************/



